home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / MacApp Release 10 / MacApp Release 10 - HD Ready / Libraries / Core / Sources / UDebug.cp < prev    next >
Encoding:
Text File  |  1996-04-03  |  28.6 KB  |  1,050 lines  |  [TEXT/MPS ]

  1. //----------------------------------------------------------------------------------------
  2. // UDebug.cp
  3. // Copyright © 1984-96 by Apple Computer, Inc. All rights reserved.
  4. //----------------------------------------------------------------------------------------
  5.  
  6. #ifndef __UDEBUG__
  7. #include "UDebug.h"
  8. #endif
  9.  
  10. // MacApp
  11.  
  12. #ifndef __UCOREGLOBALS__
  13. #include "UCoreGlobals.h"
  14. #endif
  15.  
  16. #ifndef __UCOREUTILITIES__
  17. #include "UCoreUtilities.h"
  18. #endif
  19.  
  20. #ifndef __UMEMORY__
  21. #include "UMemory.h"
  22. #endif
  23.  
  24. #ifndef __USEGMENTS__
  25. #include "USegments.h"
  26. #endif
  27.  
  28. #ifndef __UTHEDEBUGGER__
  29. #include "UTheDebugger.h"
  30. #endif
  31.  
  32. // Toolbox
  33.  
  34. #if qDebug || qTheDebugger
  35.     #ifndef __LOWMEM__
  36.     #include <LowMem.h>
  37.     #endif
  38. #endif
  39.  
  40. #if qDebug && qSegments
  41.     #ifndef __RESOURCES__
  42.     #include <Resources.h>
  43.     #endif
  44. #endif
  45.  
  46. #ifndef SYMANTEC_CPLUS
  47.     #ifndef __UNMANGLER__
  48.     #include "Unmangler.h"
  49.     #endif
  50. #endif
  51.  
  52. // ANSI
  53.  
  54. #ifndef __STDIO__
  55. #include <stdio.h>
  56. #endif
  57.  
  58. // Apple Specials
  59.     
  60. #if qDebug && !qPowerPC
  61.     #ifndef __DISASMLOOKUP__
  62.     #include "DisAsmLookup.h"
  63.     #endif
  64. #endif
  65.  
  66. #ifndef __MWERKS__
  67.     #ifndef __FCNTL__
  68.     #include "fcntl.h"
  69.     #endif
  70.     
  71.     #ifndef __IOCTL__
  72.     #include "ioctl.h"
  73.     #endif
  74. #endif
  75.  
  76. // Voodoo Monkey
  77.  
  78. #ifndef __NUBINSPECTORHOOKS__
  79. #include "NubInspectorHooks.h"
  80. #endif
  81.  
  82. // Metrowerks
  83.  
  84. #ifdef __MWERKS__
  85.     #ifndef __TRAPS__
  86.     #include <Traps.h>
  87.     #endif    
  88. #endif
  89.  
  90. #if (qDebug || qTheDebugger) && defined(__MWERKS__)
  91.     #ifndef __CWDEBUG__
  92.     #include "CWDebug.h"
  93.     #endif
  94. #endif
  95.  
  96.  
  97. //----------------------------------------------------------------------------------------
  98. // Procedure pointer typedefs
  99. //----------------------------------------------------------------------------------------
  100.  
  101. #if qDebug || qTheDebugger
  102.  
  103. typedef long(*GetProcPtr)(Ptr buffer, long count);
  104. typedef void(*PutProcPtr)(Ptr buffer, long count);
  105.  
  106. #endif    // qDebug || qTheDebugger
  107.  
  108. //----------------------------------------------------------------------------------------
  109. // struct IOPort: Used to hook MPW StdErr, StdIn, StdOut
  110. //----------------------------------------------------------------------------------------
  111.  
  112. #if qDebug || qTheDebugger
  113.  
  114. #if PRAGMA_ALIGN_SUPPORTED
  115. #pragma options align=mac68k
  116. #endif
  117. struct IOPort
  118. {
  119.     unsigned char filler[12];
  120.     long count;
  121.     Ptr bufp;
  122. };
  123. #if PRAGMA_ALIGN_SUPPORTED
  124. #pragma options align=reset
  125. #endif
  126.  
  127. #endif    // qDebug || qTheDebugger
  128.  
  129. Boolean gHighLevelDebuggerRunning;                    // True if we were able to launch
  130.                                                     // SourceBug, Sade OR Jasik running
  131.  
  132.  
  133. //----------------------------------------------------------------------------------------
  134. // Global variable definitions.
  135. //----------------------------------------------------------------------------------------
  136.  
  137. #if qDebug
  138.  
  139. Boolean gUserFlag1;
  140.  
  141. Boolean gUserFlag2;
  142.  
  143. Boolean gUserFlag3;
  144.  
  145. Boolean gAssumeFocused = TRUE;                        // make TView::AssumeFocused actually
  146.                                                     // check focus.
  147.  
  148. Boolean gDebugPrinting;
  149.  
  150. Boolean gIntenseDebugging;
  151.  
  152. Boolean gReportEvent;
  153.  
  154. Boolean gReportMenuChoices;
  155.  
  156. Boolean gShowCursorRegion;
  157.  
  158. Boolean gShowHelpRegion;
  159.  
  160. Boolean gShowInvalidations;                            // make TWindow::InvalidVRect
  161.                                                     // graphically show the invalidation
  162.                                                     // region
  163.                                                     
  164. Boolean gShowSleepRegion;
  165.  
  166. Boolean gMemMgtBreak;
  167.  
  168. Boolean gRsrcReport;
  169.     // Report resource maximums to the debugger window.
  170.  
  171. Boolean gSegReport;
  172.     // Report segment loadings to the debugger window.
  173.  
  174. //Boolean gMastReport = TRUE;
  175.  
  176. short gCurrentDebugger = kxNoDebugger;    // constants defined in CWDebug.h
  177.  
  178. #endif    // qDebug
  179.  
  180. //----------------------------------------------------------------------------------------
  181. // Static variable definitions.
  182. //----------------------------------------------------------------------------------------
  183.  
  184. #if qDebug || qTheDebugger
  185. #if !(THINK_CPLUS || SYMANTEC_CPLUS) && !defined(__MWERKS__)
  186.  
  187. static GetProcPtr pGetProc;                        // Address of the Proc to Handle
  188.                                                 // Read requests Function
  189.                                                 // DEVGETTEXT(textBuf: Ptr, byteCount:
  190.                                                 // longint): longint;
  191.  
  192. static PutProcPtr pPutProc;                        // Address of the Proc to Handle
  193.                                                 // WriteLn requests Procedure
  194.                                                 // DEVPUTTEXT(textBuf: Ptr, byteCount:
  195.                                                 // longint);
  196. #endif // !(THINK_CPLUS || SYMANTEC_CPLUS) && !defined(__MWERKS__)
  197.  
  198. static Boolean pUDebugInitialized;                // True if InitUDebug has been called
  199.  
  200. #endif // (qDebug || qTheDebugger)
  201.  
  202. #if (qDebug || qTheDebugger)
  203.  
  204. static ProcessSerialNumber pDebuggerProcess;    // The process number of the high level
  205.                                                 // debugger if there is one.
  206.  
  207. #endif    // qDebug
  208.  
  209.  
  210. //========================================================================================
  211. // GLOBAL Procedures
  212. //========================================================================================
  213.  
  214. #if qDebug || qTheDebugger
  215.  
  216. #if qDebug
  217. static void FindHighLevelDebugger();
  218. static Boolean FindDebuggerProcess(OSType sig, short debugger);
  219. #endif
  220.  
  221. static void InstallWriteLnHook();
  222.  
  223. #if !(THINK_CPLUS || SYMANTEC_CPLUS) && !defined(__MWERKS__)
  224. static GetProcPtr SetGetProc(GetProcPtr theGetProc);
  225. static PutProcPtr SetPutProc(PutProcPtr thePutProc);
  226. static long DebugReadLn(Ptr buffer, long byteCount);
  227. #endif // !(THINK_CPLUS || SYMANTEC_CPLUS) && !defined(__MWERKS__)
  228.  
  229. #endif
  230.  
  231. //----------------------------------------------------------------------------------------
  232. // External function definitions (no mangling).
  233. //----------------------------------------------------------------------------------------
  234.  
  235. #if !(THINK_CPLUS || SYMANTEC_CPLUS) && !defined(__MWERKS__)
  236. extern "C"
  237. {
  238.     extern long DevClose(long iop);
  239.     extern long DevIoctl(long iop,
  240.                          long command,
  241.                          void* arg);
  242.     extern long DevFAccess(char* fName,
  243.                            long command,
  244.                            void* arg);
  245.     extern long DevRead(long iop);
  246.     extern long DevWrite(long iop);
  247.  
  248.     extern long _addDevHandler(long slot,
  249.                                long dvName,
  250.                                void* dvFAccess,
  251.                                void* dvClose,
  252.                                void* dvRead,
  253.                                void* dvWrite,
  254.                                void* dvIoctl);
  255. }
  256. #endif // !(THINK_CPLUS || SYMANTEC_CPLUS) && !defined(__MWERKS__)
  257.  
  258. #if qDebug
  259.  
  260. //========================================================================================
  261. // CLASS CStackFrame
  262. //========================================================================================
  263. #undef Inherited
  264.  
  265. //----------------------------------------------------------------------------------------
  266. // CStackFrame::CStackFrame:
  267. //----------------------------------------------------------------------------------------
  268. #pragma segment MADebugger
  269.  
  270. CStackFrame::CStackFrame(void* framePtr)
  271. {
  272.     fFramePtr = (ptrdiff_t) framePtr;
  273. } // CStackFrame::CStackFrame
  274.  
  275.  
  276. //----------------------------------------------------------------------------------------
  277. // CStackFrame::CStackFrame:
  278. //----------------------------------------------------------------------------------------
  279. CStackFrame::CStackFrame(void)
  280. {
  281.     fFramePtr = (ptrdiff_t) 1;
  282. } // CStackFrame::CStackFrame
  283.  
  284.  
  285. //----------------------------------------------------------------------------------------
  286. // CStackFrame::CStackFrame:
  287. //----------------------------------------------------------------------------------------
  288. CStackFrame::CStackFrame(ptrdiff_t framePtr)
  289. {
  290.     fFramePtr = framePtr;
  291. } // CStackFrame::CStackFrame
  292.  
  293.  
  294. //----------------------------------------------------------------------------------------
  295. // CStackFrame::GetCallersStackFrame:
  296. //----------------------------------------------------------------------------------------
  297. CStackFrame CStackFrame::GetCallersStackFrame() const
  298. {
  299.     return CStackFrame(*((ptrdiff_t *) fFramePtr));
  300. } // CStackFrame::GetCallersStackFrame
  301.  
  302.  
  303. //----------------------------------------------------------------------------------------
  304. // CStackFrame::GetReturnAddress:
  305. //----------------------------------------------------------------------------------------
  306. void* CStackFrame::GetReturnAddress() const
  307. {
  308.     return *(void **) (fFramePtr + 4);
  309. } // CStackFrame::GetReturnAddress
  310.  
  311.  
  312. //----------------------------------------------------------------------------------------
  313. // CStackFrame::GetStackFramePtr:
  314. //----------------------------------------------------------------------------------------
  315. const ptrdiff_t CStackFrame::GetStackFramePtr() const
  316. {
  317.     return fFramePtr;
  318. } // CStackFrame::GetStackFramePtr
  319.  
  320.  
  321. //----------------------------------------------------------------------------------------
  322. // CStackFrame::GetParametersPtr:
  323. //----------------------------------------------------------------------------------------
  324. const ptrdiff_t CStackFrame::GetParametersPtr() const
  325. {
  326.     return fFramePtr + 8;
  327. } // CStackFrame::GetParametersPtr
  328.  
  329.  
  330. //----------------------------------------------------------------------------------------
  331. // CStackFrame::GetParameterWord:
  332. //----------------------------------------------------------------------------------------
  333. const short& CStackFrame::GetParameterWord(short nthWord) const
  334. {
  335.     return *((short *) (fFramePtr + 8 + (nthWord - 1) * sizeof(short)));
  336. } // CStackFrame::GetParameterWord
  337.  
  338.  
  339. //----------------------------------------------------------------------------------------
  340. // CStackFrame::GetParameterDoubleWord:
  341. //----------------------------------------------------------------------------------------
  342. const long& CStackFrame::GetParameterDoubleWord(short nthDoubleWord) const
  343. {
  344.     return *((long *) (fFramePtr + 8 + (nthDoubleWord - 1) * sizeof(long)));
  345. } // CStackFrame::GetParameterDoubleWord
  346.  
  347.  
  348. //----------------------------------------------------------------------------------------
  349. // CStackFrame::GetLocalWord:
  350. //----------------------------------------------------------------------------------------
  351. const short& CStackFrame::GetLocalWord(short nthWord) const
  352. {
  353.     return *((short *) (fFramePtr - nthWord * sizeof(short)));
  354. } // CStackFrame::GetLocalWord
  355.  
  356.  
  357. //----------------------------------------------------------------------------------------
  358. // CStackFrame::GetLocalDoubleWord:
  359. //----------------------------------------------------------------------------------------
  360. const long& CStackFrame::GetLocalDoubleWord(short nthDoubleWord) const
  361. {
  362.     return *((long *) (fFramePtr - nthDoubleWord * sizeof(long)));
  363. } // CStackFrame::GetLocalDoubleWord
  364.  
  365.  
  366. //----------------------------------------------------------------------------------------
  367. // CStackFrame::LooksValid:
  368. //----------------------------------------------------------------------------------------
  369. Boolean CStackFrame::LooksValid() const
  370. {
  371. #if qPowerPC
  372. #define GetCurStackTop() 0
  373. #endif
  374.  
  375.     return !odd((long) fFramePtr) && 
  376.                 fFramePtr < (ptrdiff_t) LMGetCurStackBase() &&
  377.                     fFramePtr > (ptrdiff_t) GetCurStackTop();
  378.  
  379. } // CStackFrame::LooksValid
  380.  
  381.  
  382. //----------------------------------------------------------------------------------------
  383. // CStackFrame::operator==:
  384. //----------------------------------------------------------------------------------------
  385. Boolean CStackFrame::operator==(const CStackFrame& stackFrame) const
  386. {
  387.     return fFramePtr == stackFrame.fFramePtr;
  388. } // CStackFrame::operator==
  389.  
  390.  
  391. //----------------------------------------------------------------------------------------
  392. // CStackFrame::operator!=:
  393. //----------------------------------------------------------------------------------------
  394. Boolean CStackFrame::operator!=(const CStackFrame& stackFrame) const
  395. {
  396.     return fFramePtr != stackFrame.fFramePtr;
  397. } // CStackFrame::operator!=
  398.  
  399.  
  400.  
  401. //========================================================================================
  402. // CLASS CStackFrameIterator
  403. //========================================================================================
  404. #undef Inherited
  405. #define Inherited CIterator
  406.  
  407. //----------------------------------------------------------------------------------------
  408. // CStackFrameIterator::CStackFrameIterator:
  409. //----------------------------------------------------------------------------------------
  410. #pragma segment MADebugger
  411.  
  412. CStackFrameIterator::CStackFrameIterator(CStackFrame topFrame)
  413. {
  414.     fTopFrame = topFrame;
  415.     this->Reset();
  416. } // CStackFrameIterator::CStackFrameIterator
  417.  
  418.  
  419. //----------------------------------------------------------------------------------------
  420. // CStackFrameIterator::More:
  421. //----------------------------------------------------------------------------------------
  422. Boolean CStackFrameIterator::More()
  423. {
  424.     return fCurrentFrame.LooksValid();
  425. } // CStackFrameIterator::More
  426.  
  427.  
  428. //----------------------------------------------------------------------------------------
  429. // CStackFrameIterator::Reset:
  430. //----------------------------------------------------------------------------------------
  431. void CStackFrameIterator::Reset()
  432. {
  433.     fCurrentFrame = this->FirstFrame();
  434. } // CStackFrameIterator::Reset
  435.  
  436.  
  437. //----------------------------------------------------------------------------------------
  438. // CStackFrameIterator::FirstFrame:
  439. //----------------------------------------------------------------------------------------
  440. CStackFrame CStackFrameIterator::FirstFrame()
  441. {
  442.     return fTopFrame;
  443. } // CStackFrameIterator::FirstFrame
  444.  
  445.  
  446. //----------------------------------------------------------------------------------------
  447. // CStackFrameIterator::NextFrame:
  448. //----------------------------------------------------------------------------------------
  449. CStackFrame CStackFrameIterator::NextFrame()
  450. {
  451.     this->Advance();
  452.     return fCurrentFrame;
  453. } // CStackFrameIterator::NextFrame
  454.  
  455.  
  456. //----------------------------------------------------------------------------------------
  457. // CStackFrameIterator::Advance:
  458. //----------------------------------------------------------------------------------------
  459. void CStackFrameIterator::Advance()
  460. {
  461.     if (this->More())
  462.         fCurrentFrame = fCurrentFrame.GetCallersStackFrame();
  463. } // CStackFrameIterator::Advance
  464.  
  465.  
  466. #endif // qDebug
  467.  
  468. //========================================================================================
  469. // GLOBAL Procedures
  470. //========================================================================================
  471. #undef Inherited
  472.  
  473. //----------------------------------------------------------------------------------------
  474. // InitUDebug: essential initialization (segTable, nonRes left in for compatibility (2.0)
  475. //----------------------------------------------------------------------------------------
  476. #pragma segment MAInit
  477.  
  478. #if qDebug || qTheDebugger
  479.  
  480. void InitUDebug()
  481. {
  482.     if ( TheDbgr_IsInstalled() ) 
  483.     {
  484. #if qTheDebugger
  485.         gHighLevelDebuggerRunning = TRUE;
  486.         InstallWriteLnHook();
  487.         TheDbgr_Init_Ext_Dbgr();        // Initialize Hooks for Jasik
  488.         gCurrentDebugger = kxJasik;
  489. #endif
  490.     }
  491. #if qDebug
  492.     else
  493.     {
  494.         gHighLevelDebuggerRunning = FALSE;
  495.         FindHighLevelDebugger();
  496.         // MA_REGISTER_CLASS(TDebugFlagsView);    // Registered in IApplication
  497.         InstallWriteLnHook();
  498.     }
  499. #endif
  500.     
  501.     pUDebugInitialized = TRUE;
  502. } // InitUDebug
  503.  
  504. #endif // qDebug || qTheDebugger
  505.  
  506. //----------------------------------------------------------------------------------------
  507. // FindHighLevelDebugger:
  508. //----------------------------------------------------------------------------------------
  509. #pragma segment MAInit
  510.  
  511. #if qDebug
  512.  
  513. void FindHighLevelDebugger()
  514. {
  515.     // First, check to see if the NutraBug Nub exists.
  516.     if (NubIsInstalled())
  517.         gHighLevelDebuggerRunning = TRUE;
  518.  
  519.     // Check to see if one of the high level debuggers are running (SourceBug or Sade). 
  520.     // If so then we will send debug output to it. 
  521.     Boolean found = FindDebuggerProcess('Objr', kxSourceBug);    // Is SourceBug running?
  522.     if (!found)
  523.         found = FindDebuggerProcess('sade', kxSade);            // Is Sade running?
  524.     if (!found)
  525.         found = FindDebuggerProcess('MWDB', kxMWDebug68K);        // Is MWDebug68K running?
  526.     if (!found)
  527.         found = FindDebuggerProcess('MPDB', kxMWDebugPPC);        // Is MWDebugPPC running?
  528.     if (!found)
  529.         found = FindDebuggerProcess('R2Db', kxR2DbPPC);            // Is Apple's R2DbPPC running?
  530.     if (!found)
  531.         found = FindDebuggerProcess('Alar', kxR2Db68K);            // Is Apple's R2Db68K running?
  532.     if (!found)
  533.         found = FindDebuggerProcess('sDeb', kxVooDoo);            // Is VooDooMonkey running?
  534.     
  535.     gHighLevelDebuggerRunning = found;
  536.     if (!found)
  537.         gCurrentDebugger = kxNoDebugger;
  538. }
  539.  
  540. #endif // qDebug
  541.  
  542. //----------------------------------------------------------------------------------------
  543. // FindDebuggerProcess
  544. //----------------------------------------------------------------------------------------
  545. #pragma segment MAInit
  546.  
  547. #if qDebug
  548.  
  549. Boolean FindDebuggerProcess(OSType sig, short debugger)
  550. {
  551.     ProcessSerialNumber psn;
  552.     OSErr err = FindProcessBySignature(sig, psn, NULL);
  553.     Boolean found = (err == noErr);
  554.     if (found)
  555.     {
  556.         gCurrentDebugger = debugger;
  557.         pDebuggerProcess = psn;
  558.     }
  559.     return found;
  560. }
  561.  
  562. #endif // qDebug
  563.  
  564. //----------------------------------------------------------------------------------------
  565. // DebugCanReadLn: Returns true if you can readln to the user
  566. //----------------------------------------------------------------------------------------
  567. #pragma segment Main
  568.  
  569. #if qDebug
  570.  
  571. Boolean DebugCanReadLn()
  572. {
  573.     return FALSE;
  574. } // DebugCanReadLn
  575.  
  576. #endif    // qDebug
  577.  
  578. //----------------------------------------------------------------------------------------
  579. // DebugCanWriteLn: Returns true if you can writeln to the user
  580. //----------------------------------------------------------------------------------------
  581. #pragma segment Main
  582.  
  583. #if qDebug
  584.  
  585. Boolean DebugCanWriteLn()
  586. {
  587.     return pUDebugInitialized;
  588. } // DebugCanWriteLn
  589.  
  590. #endif
  591.  
  592. //----------------------------------------------------------------------------------------
  593. // EachFrameDo:
  594. //----------------------------------------------------------------------------------------
  595. #pragma segment MAUtilitiesRes
  596.  
  597. #if qDebug
  598.  
  599. void EachFrameDo(CStackFrame baseFrame,
  600.                  DoToFrameType DoToFrame,
  601.                  void* yourDataPtr)
  602. {
  603.     CStackFrameIterator iter(baseFrame);
  604.     CStackFrame frame;
  605.     
  606.     for (frame = iter.FirstFrame(); iter.More(); frame = iter.NextFrame())
  607.     {
  608.         DoToFrame(frame, yourDataPtr);
  609.     }
  610. } // EachFrameDo
  611.  
  612. #endif    // qDebug
  613.  
  614. //----------------------------------------------------------------------------------------
  615. // GetCallersMethodName:
  616. //----------------------------------------------------------------------------------------
  617. #pragma segment Main
  618.  
  619. #if qDebug
  620.  
  621. void GetCallersMethodName(MAName& s)
  622. {
  623. #if qPowerPC
  624.     s = "PowerPC";
  625. #else
  626.     CStackFrame stackFrame(GetCurStackFramePtr());
  627.     GetMethodName(stackFrame.GetReturnAddress(), s); // report about our caller"s caller 
  628. #endif
  629. } // GetCallersMethodName
  630.  
  631. #endif    // qDebug
  632.  
  633. //----------------------------------------------------------------------------------------
  634. // GetMethodName: GetMethodName returns the name of the method (or procedure) in which pc
  635. // points.
  636. //----------------------------------------------------------------------------------------
  637. #pragma segment Main
  638.  
  639. #if qDebug
  640.  
  641. void GetMethodName(void* pc, MAName& s)
  642. {
  643.     MAName    discardStr;
  644.     GetProcName(pc, discardStr, s);
  645. } // GetMethodName
  646.  
  647. #endif    // qDebug
  648.  
  649. //----------------------------------------------------------------------------------------
  650. // GetProcName: GetProcName returns the name of the procedure or function in which pc
  651. // points. If it is in a method, then it return"s the name of the method"s class in
  652. // className.
  653. //----------------------------------------------------------------------------------------
  654. #pragma segment Main
  655.  
  656. #if qDebug
  657.  
  658. void GetProcName(void* 
  659. #if !qPowerPC
  660.     pc
  661. #endif
  662.     , ClassName& className, MAName& procName)
  663. {
  664. #if !qPowerPC
  665.     if (pc != NULL && !odd((long) pc))
  666.     {
  667.         void* nextPC;
  668.         CStr255 localProcName;
  669.  
  670.         Ptr limit = (Ptr) ((ptrdiff_t) pc + 32767);
  671. //••• SRF Codewarrior 8 doesn't have a CFM68K stub that includes endOfModule
  672. #if !(qModelCFM && defined(__MWERKS__))
  673.         while (!endOfModule(pc, limit, (char *) &localProcName, &nextPC))
  674.         {
  675.             if (pc >= limit)
  676.             {
  677.                 className.Empty();
  678.                 procName.Empty();
  679.                 localProcName.Empty();
  680.                 return;
  681.             }
  682.             else
  683.                 pc = (void *) ((ptrdiff_t) pc + 2);
  684.         }
  685. #endif
  686.         char cProcName[256];
  687.  
  688.         if (unmangle(cProcName, (char *) &localProcName, 255) < 1)
  689.             procName = localProcName;
  690.         else
  691.             procName = cProcName;
  692.  
  693.         short index = procName.Pos(".");
  694.         if (index != 0)
  695.             className = procName.Copy(1, index - 1);
  696.         else
  697.             className.Empty();
  698.     }
  699.     else
  700. #endif
  701.     {
  702.         className.Empty();
  703.         procName.Empty();
  704.     }
  705. } // GetProcName
  706.  
  707. #endif    // qDebug
  708.  
  709. //----------------------------------------------------------------------------------------
  710. // ShowSegments:
  711. //----------------------------------------------------------------------------------------
  712. #pragma segment MADebugger
  713.  
  714. #if qDebug
  715.  
  716. void ShowSegments()
  717. {
  718. #if qSegments
  719.     // Show segment information.
  720.  
  721.     fprintf(stderr, "[•=resident L=loaded U=unloaded -=purged], H=high water, E=ever loaded\n");
  722.  
  723.     long codeRes = 0;                                    // counts size of code segments 
  724.     long i = 0;
  725.     for (CCodeSegment * codeSegment = gCodeSegs; codeSegment; codeSegment = codeSegment->fNextCodeSegment)
  726.     {
  727.         ++i;
  728.         Handle seg = codeSegment->fCodeSeg;
  729.         if (seg)
  730.         {
  731.             short        id;
  732.             CStr255        name;
  733.             ResType        t;
  734.  
  735.             GetResInfo(seg, &id, &t, name);
  736.  
  737.             WritePtr((long) seg);
  738.             //    if (seg == NULL)
  739.             //        fprintf(stderr, "NULL");
  740.             //    else
  741.             //        fprintf(stderr, "%X", (long) seg);
  742.  
  743.             fprintf(stderr, "  Seg#:%3d ", id);
  744.  
  745.             if (codeSegment->fResidentSeg)
  746.                 fprintf(stderr, "• ");
  747.             else if (IsHandlePurged(seg))
  748.                 fprintf(stderr, "- ");
  749.             else if (codeSegment->fSegLoaderLoaded)
  750.                 fprintf(stderr, "L ");
  751.             else
  752.                 fprintf(stderr, "U ");
  753.  
  754.             if (codeSegment->fHighWater)
  755.                 fprintf(stderr, "H ");
  756.             else
  757.                 fprintf(stderr, "- ");
  758.  
  759.             if (codeSegment->fEverLoaded)
  760.                 fprintf(stderr, "E ");
  761.             else
  762.                 fprintf(stderr, "- ");
  763.  
  764.             fprintf(stderr, " %s ", (const char *) name);
  765.  
  766.             fprintf(stderr, "%ld bytes\n", codeSegment->GetSize());
  767.  
  768.             codeRes += codeSegment->fSegSize + 8;
  769.         }
  770.     }
  771.  
  772.     fprintf(stderr, "\n");
  773.     fprintf(stderr, "Total # segments = %d \n" , i);
  774.     fprintf(stderr, "Total loaded code = %ld\n", codeRes);
  775.  
  776.     long lockedSpace = CGrowZoneHook::TotalTempSize(TRUE);
  777.     long totalSpace = CGrowZoneHook::TotalTempSize(FALSE);
  778.     fprintf(stderr,"  Current temp space: locked = %ld, unlocked = %ld, total = %ld\n",
  779.             lockedSpace, totalSpace - lockedSpace, totalSpace);
  780. #endif
  781. } // ShowSegments
  782.  
  783. #endif    // qDebug
  784.  
  785. //========================================================================================
  786. // Debug output with Apple's runtime library
  787. //========================================================================================
  788.  
  789. #if qDebug || qTheDebugger
  790. #if !(THINK_CPLUS || SYMANTEC_CPLUS) && !defined(__MWERKS__)
  791.  
  792. //----------------------------------------------------------------------------------------
  793. // DevFAccess:
  794. //----------------------------------------------------------------------------------------
  795. #pragma segment Main
  796.  
  797. long DevFAccess(char* fName, long command, void* /* arg */)
  798. {
  799.     const Boolean CaseSensitive = TRUE;
  800.     const Boolean DiacritSensitive = TRUE;
  801.     const CStr255 fileName = fName;
  802.  
  803.     const CStr255 kConsoleName = "dev:console";        // console device name
  804.     if (EqualString(fileName, kConsoleName, !CaseSensitive, DiacritSensitive))
  805.         switch (command)
  806.         {
  807.             case F_OPEN:
  808.                 return 0;
  809.  
  810.             default:
  811.                 return -1;
  812.         }
  813.     else
  814.         return -1;
  815. } // DevFAccess
  816.  
  817. //----------------------------------------------------------------------------------------
  818. // DevClose:
  819. //----------------------------------------------------------------------------------------
  820. #pragma segment Main
  821.  
  822. long DevClose(long)
  823. {
  824.     return 0;
  825. } // DevClose
  826.  
  827. //----------------------------------------------------------------------------------------
  828. // DevRead:
  829. //----------------------------------------------------------------------------------------
  830. #pragma segment Main
  831.  
  832. long DevRead(long iop)
  833. {
  834.     IOPort * iopPtr = (IOPort *)iop;
  835.     long bytesRead;
  836.  
  837.     bytesRead = pGetProc(iopPtr->bufp, iopPtr->count);
  838.     iopPtr->bufp += bytesRead;
  839.     iopPtr->count -= bytesRead;
  840.     return 0;
  841. } // DevRead
  842.  
  843. //----------------------------------------------------------------------------------------
  844. // DevWrite:
  845. //----------------------------------------------------------------------------------------
  846. #pragma segment Main
  847.  
  848. long DevWrite(long iop)
  849. {
  850.     IOPort * iopPtr = (IOPort *)iop;
  851.  
  852.     pPutProc(iopPtr->bufp, iopPtr->count);
  853.     iopPtr->count = 0;
  854.     return 0;
  855. } // DevWrite
  856.  
  857. //----------------------------------------------------------------------------------------
  858. // DevIoctl:
  859. //----------------------------------------------------------------------------------------
  860. #pragma segment Main
  861.  
  862. long DevIoctl(long /* iop */,
  863.               long command,
  864.               void* /* arg */)
  865. {
  866.     switch (command)
  867.     {
  868.         case FIOINTERACTIVE:
  869.         case TIOFLUSH:
  870.             return 0;
  871.  
  872.         default:
  873.             return -1;
  874.     }
  875. } // DevIoctl
  876.  
  877. //----------------------------------------------------------------------------------------
  878. // SetGetProc:
  879. //----------------------------------------------------------------------------------------
  880. #pragma segment Main
  881.  
  882. GetProcPtr SetGetProc(GetProcPtr theGetProc)
  883. {
  884.     GetProcPtr returnProc = pGetProc;
  885.     pGetProc = theGetProc;
  886.     return returnProc;
  887. } // SetGetProc
  888.  
  889. //----------------------------------------------------------------------------------------
  890. // SetPutProc:
  891. //----------------------------------------------------------------------------------------
  892. #pragma segment Main
  893.  
  894. PutProcPtr SetPutProc(PutProcPtr thePutProc)
  895. {
  896.     PutProcPtr returnProc = pPutProc;
  897.     pPutProc = thePutProc;
  898.     return returnProc;
  899. } // SetPutProc
  900.  
  901. //----------------------------------------------------------------------------------------
  902. // DebugReadLn:
  903. //----------------------------------------------------------------------------------------
  904. #pragma segment MADebugger
  905.  
  906. long DebugReadLn(Ptr /*buffer*/, long /*byteCount*/)
  907. {
  908.     return 0;
  909. } // DebugReadLn
  910.  
  911. #endif // !(THINK_CPLUS || SYMANTEC_CPLUS) && !defined(__MWERKS__)
  912. #endif    // qDebug || qTheDebugger
  913.  
  914. //----------------------------------------------------------------------------------------
  915. // ConfirmHighLevelDebugger:
  916. //----------------------------------------------------------------------------------------
  917. #pragma segment Main
  918.  
  919. #if qDebug || qTheDebugger
  920.  
  921. void ConfirmHighLevelDebugger()
  922. {
  923. #if qTheDebugger
  924.     if (gExtDbgr_Info.isBeingDebugged || TheDbgr_IsInstalled())    // keeps MMU from complaining
  925.         gHighLevelDebuggerRunning = TRUE;
  926. #endif // qTheDebugger
  927. #if qDebug
  928. #if qTheDebugger
  929.     else 
  930. #endif // qTheDebugger
  931.     if (gHighLevelDebuggerRunning)
  932.     {
  933.         if (NubIsInstalled())
  934.             gHighLevelDebuggerRunning = TRUE;
  935.  
  936.         OSErr err;
  937.         ProcessInfoRec processInfo;
  938.         
  939.         // Check to see if the high level debugger is still running. The user could have
  940.         // closed the application. If it is no longer running then just quit sending
  941.         // output to the debugger.
  942.         
  943.         processInfo.processInfoLength = sizeof(ProcessInfoRec);
  944.         processInfo.processName = NULL;
  945.         processInfo.processAppSpec = NULL;
  946.         
  947.         err = GetProcessInformation(&pDebuggerProcess, &processInfo);
  948.         if (err != noErr)
  949.         {
  950.             gHighLevelDebuggerRunning = FALSE;
  951.             gCurrentDebugger = kxNoDebugger;
  952.         }
  953.     }
  954. #endif // qDebug
  955. } // ConfirmHighLevelDebugger
  956.  
  957. #endif    // qDebug || qTheDebugger
  958.  
  959. //----------------------------------------------------------------------------------------
  960. // DebugWriteLnHook:
  961. //----------------------------------------------------------------------------------------
  962. #pragma segment MADebugger
  963.  
  964. #if qDebug || qTheDebugger
  965.  
  966. void DebugWriteLnHook(Ptr textBuf, long byteCount)
  967. {
  968.     ConfirmHighLevelDebugger();
  969.     
  970.     CStr255 debugStr;
  971.     Ptr p = textBuf;
  972.     while (byteCount > 0) 
  973.     {
  974.         long len = Min(byteCount, 250);
  975.         int i = 0;
  976.         char* d = ((char*)&debugStr) + 1;
  977.         while (i < len)
  978.         {
  979.             char c = *p++;
  980.             *d++ = c;
  981.             if ((c == '\r') || (c == '\n'))
  982.             {
  983.                 len = i + 1;
  984.                 break;
  985.             }
  986.             i++;
  987.         }
  988.         debugStr.Length() = (unsigned char) i;
  989.  
  990.         if ((gCurrentDebugger == kxSourceBug) || (gCurrentDebugger == kxVooDoo) ||
  991.             (gCurrentDebugger == kxSade))
  992.         {
  993.             debugStr += '\n';
  994.             SysBreakFunc(debugStr);
  995.         }
  996.         else        
  997. #if qTheDebugger
  998.         if (gExtDbgr_Info.isBeingDebugged || TheDbgr_IsInstalled())
  999.         {
  1000.             debugStr += '\n';
  1001.             SysBreakFunc(debugStr);
  1002.         }
  1003.         else        
  1004. #endif
  1005.         {
  1006.             debugStr += ";g";
  1007.             DebugStr(debugStr);
  1008.         }
  1009.         
  1010.         byteCount -= len;
  1011.     }
  1012. }
  1013.  
  1014. #endif // qDebug || qTheDebugger
  1015.  
  1016. //----------------------------------------------------------------------------------------
  1017. // InstallWriteLnHook:
  1018. //----------------------------------------------------------------------------------------
  1019. #pragma segment MADebugger
  1020.  
  1021. #if qDebug || qTheDebugger
  1022.  
  1023. void InstallWriteLnHook()
  1024. {
  1025. #if defined(__MWERKS__)
  1026.     InitCWDebug();
  1027. #elif (THINK_CPLUS || SYMANTEC_CPLUS)
  1028.     // Don't have Symantec debug support yet
  1029. #else
  1030.     fclose(stdin);
  1031.     fclose(stdout);
  1032.     fclose(stderr);
  1033.     const short _CODEV = 1;                        // console device number
  1034.     _addDevHandler(_CODEV, 0, DevFAccess, DevClose, DevRead, DevWrite, DevIoctl);
  1035.     freopen("dev:console", "r", stdin);
  1036.     freopen("dev:console", "a", stdout);
  1037.     freopen("dev:console", "a", stderr);
  1038.     SetPutProc(DebugWriteLnHook);
  1039.     setvbuf(stderr, NULL, _IOLBF, 128);
  1040.     SetGetProc(DebugReadLn);
  1041. #endif
  1042. }
  1043.  
  1044. #endif // qDebug || qTheDebugger
  1045.  
  1046. //----------------------------------------------------------------------------------------
  1047. // End of UDebug.cp
  1048.  
  1049. #pragma segment Inline
  1050.